package cn.tiga.basic.service.impl;


import cn.tiga.basic.constant.BaseConstants;
import cn.tiga.basic.dto.SmsCodeDto;
import cn.tiga.basic.exception.BusinessException;
import cn.tiga.basic.service.IVerifyCodeService;
import cn.tiga.basic.utils.StrUtils;
import cn.tiga.basic.utils.VerifyCodeUtils;
import cn.tiga.user.domain.User;
import cn.tiga.user.mapper.UserMapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Override
    public String getImageCode(String imageCodeKey) {
        // 1.判断参数是否为空
        if (StringUtils.isEmpty(imageCodeKey)){
            throw new BusinessException("参数不能为空，请传递正确参数！");
        }
        // 2.获取到随机4位字符串
        String imageCode = StrUtils.getComplexRandomString(4);
        // 3.使用工具类生成Base64图形验证码字符串
        String imageBase64Str = VerifyCodeUtils.VerifyCode(100, 30, imageCode);
        // 4.根据key、value保存到Redis中，并设置三分钟有效
        redisTemplate.opsForValue().set(imageCodeKey, imageCode, 5, TimeUnit.MINUTES);
        return imageBase64Str;
    }

    /**
     * @Title: smsCode
     * @Description: 发送短信验证码
     * @Author: Mr.She
     * @Version: 1.0
     * @Date:  2022/7/6 10:38
     * @Parameters: [smsCodeDto]
     * @Return void
     */
    @Override
    public void smsCode(SmsCodeDto smsCodeDto) {
        // 获取参数
        String phone = smsCodeDto.getPhone();
        // 图形验证码的key
        String imageCodeKey = smsCodeDto.getImageCodeKey();
        // 图形验证码的value
        String imageCodeValue = smsCodeDto.getImageCodeValue();
        //后端
        //1.非空校验
        if (StringUtils.isEmpty(phone)){
            throw new BusinessException("参数不能为空！");
        }
        //2.判断图形验证码是否正确以及存在
        Object imageCodeValueTmp = redisTemplate.opsForValue().get(imageCodeKey);
        if (imageCodeValueTmp == null){
            throw new BusinessException("验证码已过期，请重新获取！");
        }
        // 忽略大小写比较图形验证码是否正确
        if (!imageCodeValueTmp.toString().equalsIgnoreCase(imageCodeValue)){
            throw new BusinessException("验证码错误，请重新输入！");
        }
        //3.判断用户是否已注册，如果已注册提示用户
        User user = userMapper.loadByPhone(phone);
        if (user != null){
            throw new BusinessException("用户已注册，请直接登录，如果忘记密码，请点击忘记密码！");
        }
        //4.根据电话号码拼接业务键，去redis中获取对应的value值，判断是否存在
        String phoneCodeKey = BaseConstants.VerifyCodeConstant.BUSINESS_REGISTER_KEY + phone;
        Object phoneCodeValue = redisTemplate.opsForValue().get(phoneCodeKey);
        //0.定义一个空字符串，专门用来接收验证码
        String phoneCode = "";
        if (phoneCodeValue == null){//1.不存在
            //1.生成新的随机验证码,并赋值给空字符串
            phoneCode = StrUtils.getComplexRandomString(4);
        }else {//2.存在
            //1.分割value得到时间戳，跟现在的时间戳做减法，如果小于1分钟的毫秒数抛出异常
            String[] phoneCodeValueTmp = phoneCodeValue.toString().split(":");
            // 之前存入code时，我们记录的时间戳
            Long oldTime = Long.valueOf(phoneCodeValueTmp[0]);
            // 现在的时间戳
            Long nowTime = System.currentTimeMillis();
            if (nowTime - oldTime < 1*60*1000){
                throw new BusinessException("请一分钟之后再获取！");
            }
            //2.将旧的验证码赋值给空字符串
            phoneCode = phoneCodeValueTmp[1];
        }
        //5.通过业务键+phone作为key，验证码+时间戳作为value，存入redis，设置为三分钟有效
        String phoneCodeRedis = System.currentTimeMillis() + ":" + phoneCode;
        redisTemplate.opsForValue().set(phoneCodeKey, phoneCodeRedis, 3, TimeUnit.MINUTES);
        //6.发送短信验证码
        // SmsUtils.sendCode(phone, "亲，您的验证码是："+ phoneCode);
        System.out.println("亲，您的验证码是："+ phoneCode);
    }

}
